package com.tianji.learning.task;

import com.tianji.common.utils.ObjectUtils;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.utils.TableNameContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.util.List;

import static com.tianji.common.constants.Constant.POINTS_BOARDS_TABLENAME_PREFIX;
import static com.tianji.common.utils.DateUtils.DATE_SUFFIX_FORMATTER;
import static com.tianji.learning.constants.RedisConstants.POINTS_BOARDS_KEY_PREFIX;

/**
 * @author Administrator
 * @version 1.0
 * @description: TODO
 * @date 2025/10/31 16:12
 */

@Slf4j
@Component
@RequiredArgsConstructor
public class PointsBoardPersistentTask {
    private final IPointsBoardSeasonService seasonService;
    private final IPointsBoardService boardService;
    private final StringRedisTemplate redisTemplate;

    /**
     * 1、创建上一个赛季的历史积分排行榜表
     */
    @XxlJob("createTableJob")
    public void createTable(){
        // 1、获取上个月的时间
        LocalDate lastMonthDate = LocalDate.now().minusMonths(1);

        // 2、根据时间查询上个月的赛季ID
        Integer seasonId = seasonService.querySeasonIdByDate(lastMonthDate);

        // 3、创建表
        boardService.createTable(seasonId);
    }

    /**
     * 2、榜单持久化
     */
    @XxlJob("savePointsBoard2DB")
    public void savePointsBoard2DB(){
        // 1、获取上个月的时间
        LocalDate lastMonthDate = LocalDate.now().minusMonths(1);

        // 2、计算动态表名
        // 2.1、查询赛季ID，拼接表名
        Integer seasonId = seasonService.querySeasonIdByDate(lastMonthDate);
        String newTableName = POINTS_BOARDS_TABLENAME_PREFIX + seasonId;

        // 2.2、将表名放入ThreadLocal,当前线程的任意位置都能获取到该表名
        TableNameContext.setTableName(newTableName);

        // 3、查询redis中的榜单数据，进行持久化
        int shardIndex = XxlJobHelper.getShardIndex();  // 0 1
        int shardTotal = XxlJobHelper.getShardTotal();  // 2

        String key = POINTS_BOARDS_KEY_PREFIX + lastMonthDate.format(DATE_SUFFIX_FORMATTER);
        int pageNo = shardIndex + 1,pageSize = 4;
        List<PointsBoard> boardList = boardService.queryCurrentBoardList(key, pageNo, pageSize);
        while (ObjectUtils.isNotEmpty(boardList)){
            for (PointsBoard board : boardList) {
                board.setId(board.getRank().longValue());
                board.setRank(null);
            }
            this.boardService.saveBatch(boardList);
            boardList = boardService.queryCurrentBoardList(key, pageNo += shardTotal, pageSize);
        }

        // 4、清理ThreadLocal，防止内存泄漏
        TableNameContext.removeTableName();
    }

    /**
     * 3、清理榜单
     * @throws InterruptedException
     */
    @XxlJob("clearPointsBoardFromRedis")
    public void clearPointsBoardFromRedis() throws InterruptedException {
        Thread.sleep(2000);
        // 1、获取上个月的时间
        LocalDate lastMonthDate = LocalDate.now().minusMonths(1);

        // 2、拼接key
        String key = POINTS_BOARDS_KEY_PREFIX + lastMonthDate.format(DATE_SUFFIX_FORMATTER);

        // 3、删除key
        redisTemplate.unlink(key); // 异步删除key,非阻塞
    }
}
